Skip to content

Conversation

@Tirtho13
Copy link

@Tirtho13 Tirtho13 commented Nov 5, 2025

Libxc interface in mrchem

This is a detailed list of things to do in the integration of Libxc into MRChem. The checklist should have all the necessary changes to complete the integration process.

This is the checklist of all the necessary changes.
NOTE: Please refrain from making commits to the checklists before the changes are made public for review. For owning a particular job, note your name at the end of the specified job. If you want to make a note, add it to the dev notes.

CMAKE files

  • Fix autocmake for libxc, currently hard coded paths in Factory.h and Functional.h. (Tirthonkor)
  • Works, but very slow --> needs optimizing (check compile flags?)
  • Update: currently not working anymore
  • Udate: working fine, but still have to make final edits

Runtime backend

  • Simultaneous support for XCFun and Libxc backends: the choice should be made at runtime based on user input, which backend to use, xcfun or libxc. (Ylva)
  • Can be decided with the keyword DFT { xc_library = libxc }, default is xcfun.

Libxc input

  • Human readable Libxc input: pass in keyword strings like GGA_X_PBE and parse them with xc_functional_get_number() to get the numerical ID (you can still trivially also support integer IDs) (Ylva)
  • I think this is done? Code needs expanded list of functionals, but as it is now, the functional name is eg. "slaterx" or "beckex" from mrchem/xcfun which gets translated (manually) to corresponding libxc functionals, "XC_LDA_X" etc.
  • Susi implemented this

Density threshold

  • Printing out the functional's density threshold since that will be really important for high precision calculations (Ylva)

To do during/after restructuring (to avoid doing it twice)

Making functionals class abstract and create new classes for libxc/xcfun inheriting from functionals.
Ylva will make a rough separation of classes and then we can update a to do list of which parts that should be done (a lot of the functional class functions are using xcfun and should be made general, but that can be done function by function).

Libxc and functional citation

  • Proper printout of the Libxc citation information; both for Libxc itself (xc_version(), xc_reference(), xc_reference_doi()) and the used functionals (see Libxc manual for examples) (Ylva) (Tirthonkor)
  • Prints citation for libxc, not yet for the used functional
  • Should use libxc function to automatically get correct citation
  • Citations for individual functionals added

Get hyb parameters from libxc

  • Checking that hybrid parameters are parsed from Libxc, not hard-coded in MRChem
  • Done

Overwrite Libxc functional settings

  • Support for overwriting Libxc functional settings; this requires defining parameter arrays for each functional used in the calculation and calling xc_func_set_ext_params for each of them before the functional is used (the parameters can change e.g. the fraction of exact exchange) (Tirthonkor)
  • This can be done in a later pull; there remains too much to be done

Testing

  • Make current xcfun-based unit tests work
  • Make current xcfun-based regression tests work
  • Make new libxc-based unit tests
  • Make new libxc-based regression tests

Documentation

  • User manual with some input examples
  • Programmer's manual outlining how the interfacing of the two libraries has been designed and implemented

@ilfreddy
Copy link
Contributor

ilfreddy commented Feb 2, 2026

@susilehtola @Tirtho13. Are you satisfied with the LibXC tests which you have now included in MRChem? Could we consider ticking those two off as well?
After that I believe this PR is ready to be reviewed IMO.

coefs = {1.0};
return;
} else if (name == "SVWN5") {
} else if (name == "SVWN5" || name == "LDA") {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LDA is a bad keyword.

Comment on lines 137 to 143
/** @brief Run a collection of grid points through Libxc or XCFun
*
* Each row corresponds to one grid point.
*
* param[in] inp_data Matrix of input values
* param[out] out_data Matrix of output values
*/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why was the comment removed?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The policy in MRChem is to include this documentation in the header files and no longer in the implementation files. This is why that has been removed. Same for all the other ones.

* efficient to have the two consecutive points in two consecutive adresses in memory
*
* param[in] inp_data Matrix of input values
* param[out] out_data Matrix of output values
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

Comment on lines 304 to 310
/** @brief Run a collection of grid points through Libxc or XCFun
*
* Each row corresponds to one grid point.
*
* param[in] inp_data Matrix of input values
* param[out] out_data Matrix of output values
*/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and here

Comment on lines -320 to -327
/** @brief Contract a collection of grid points
*
* Each row corresponds to one grid point.
*
* param[in] xc_data Matrix of functional partial derivative values
* param[in] d_data Matrix of density input values
* param[out] out_data Matrix of contracted output values
*/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and here

Comment on lines -352 to -359
/** @brief Contract a collection of grid points
*
* Each column corresponds to one set of grid points.
*
* param[in] xc_data Matrix of functional partial derivative values
* param[in] d_data Matrix of density input values
* param[out] out_data Matrix of contracted output values
*/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and here

Comment on lines -383 to -432

/** @brief Evaluates XC functional and derivatives for a given NodeIndex
*
* The electronic densities (total/alpha/beta) are given as input.
* The values of the zero order densities and their gradient are sent to xcfun.
* The output of xcfun must then be combined ("contract") with the gradients
* of the higher order densities.
*
* XCFunctional output (with k=1 and explicit derivatives):
*
* LDA: \f$ \left(F_{xc}, \frac{\partial F_{xc}}{\partial \rho}\right) \f$
*
* GGA: \f$ \left(F_{xc},
* \frac{\partial F_{xc}}{\partial \rho},
* \frac{\partial F_{xc}}{\partial \rho_x},
* \frac{\partial F_{xc}}{\partial \rho_y},
* \frac{\partial F_{xc}}{\partial \rho_z}\right) \f$
*
* Spin LDA: \f$ \left(F_{xc}, \frac{\partial F_{xc}}{\partial \rho^\alpha},
* \frac{\partial F_{xc}}{\partial \rho^\beta}\right) \f$
*
* Spin GGA: \f$ \left(F_{xc},
* \frac{\partial F_{xc}}{\partial \rho^\alpha},
* \frac{\partial F_{xc}}{\partial \rho^\beta},
* \frac{\partial F_{xc}}{\partial \rho_x^\alpha},
* \frac{\partial F_{xc}}{\partial \rho_y^\alpha},
* \frac{\partial F_{xc}}{\partial \rho_z^\alpha},
* \frac{\partial F_{xc}}{\partial \rho_x^\beta},
* \frac{\partial F_{xc}}{\partial \rho_y^\beta},
* \frac{\partial F_{xc}}{\partial \rho_z^\beta}
* \right) \f$
*
* XCFunctional output (with k=1 and gamma-type derivatives):
*
* GGA: \f$ \left(F_{xc},
* \frac{\partial F_{xc}}{\partial \rho},
* \frac{\partial F_{xc}}{\partial \gamma} \f$
*
* Spin GGA: \f$ \left(F_{xc},
* \frac{\partial F_{xc}}{\partial \rho^\alpha},
* \frac{\partial F_{xc}}{\partial \rho^\beta },
* \frac{\partial F_{xc}}{\partial \gamma^{\alpha \alpha}},
* \frac{\partial F_{xc}}{\partial \gamma^{\alpha \beta }},
* \frac{\partial F_{xc}}{\partial \gamma^{\beta \beta }}
* \right) \f$
*
* param[in] inp Input values
* param[out] xcNodes Output values
*
*/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and here

coefs = {1.0, 1.0};
return;
} else if (name == "B3LYP") {
ids = {XC_HYB_GGA_XC_B3LYP5};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is not B3LYP!!!

coefs = {1.0, 1.0};
return;
} else if (name == "B3LYP") {
ids = {XC_HYB_GGA_XC_B3LYP5};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
ids = {XC_HYB_GGA_XC_B3LYP5};
ids = {XC_HYB_GGA_XC_B3LYP};

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we need to agree on what kind of "behavior" we want the code to have. Ideally a given functional keyword (let's take B3LYP as an example) should yield the same result regardless of the dft library used. Now it is a bit unfortunate that what libxc and xcfun define as vanilla B3LYP is not the same functional (same for e.g. PBE)
Given that libxc is by far more distributed, I would say we should follow the libxc convention and have some translation mechanism in place for xcfun. The drawback from my point of view is that this will break compatibility with previous results. But I guess we need to live with that.

}

WaveFunction {
method = LDA # Wave function method (HF or DFT)
Copy link
Contributor

@susilehtola susilehtola Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"LDA" is ambigous, unless it is exchange-only. Use a proper functional.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LDA had become a (psudo) standard alias for SVWN5 which mrchem (and orca, pyscf, etc) use, this pr should not be the one to change this.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where?

Orca lists

        HFS        # Hartree-Fock Slater (Slater exchange only)
        LSD        # Local spin density (VWN-5A form)
        VWN5       # Local spin density (VWN-5)
        VWN3       # Local spin density (VWN-3)
        PWLDA      # Local spin density (PW-LDA)

There is no "LDA".

PySCF with LDA gives

XC functionals = lda
    P. A. M. Dirac.,  Math. Proc. Cambridge Philos. Soc. 26, 376 (1930)
    F. Bloch.,  Z. Phys. 57, 545 (1929)

which is just the exchange functional, like I said above.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking in the orca manual (6.1.1) can be a bit misleading, as they only specify VWN5:

att beMMrz9KsBZMZkPRYpOUde7ZCCou3aHsVmSkrKixvsg

But running a simple LDA input file shows it is running SVWN5

att q7BUd1pGgC4z9R0RjSf2cZOwwHKuVFIIlnHQLuJctYM
att JoG0u4ogBblOuOb9Ur7cx7K8vF2QBmUM6Q0oI_ANXHk

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK so Orca has documented this in the 6.1 manual; I looked at the 6.0 manual that does not have an LDA keyword.

But in PySCF LDA means something else.

There is no generally accepted meaning, which is why it should not be a keyword.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don’t mind changing the keyword in the new tests, but there are other tests that use “lda”, and I don’t think it’s a good idea to remove the possibility of calling «lda» for svwn5 in mrchem as people might expect that to work (at least not in this pr)

@ylvao ylvao removed the WIP Work in progress label Feb 2, 2026
@ylvao ylvao linked an issue Feb 3, 2026 that may be closed by this pull request
@ylvao
Copy link

ylvao commented Feb 3, 2026

Personally, I think we have a mergeable code now. It can run libxc on input demand, we have tests, the numbers are consistent and there is otherwise little change to the program, which was the goal here. There are still things to do on the libxc/dft side of the program, eg. restructuring the functional classes, fixing b3lyp, ... which can be done at a later point (it would also be good to not have too much happening in this pr considering that the commits will be smashed).

Unless there is any specific comments, I suggest we wait for the pr to be reviewed :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Libxc interface?

4 participants